﻿using System;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using FacturacionElectronica;


namespace AdmFacturacionElectronica
{
    public partial class Form1 : Form
    {
        Thread p1;
        Thread p2;
        Thread p3;
        Thread p4;
        delegate void SetTextCallback(string text);
        delegate void SetVisibilityCallback(bool estado);
        ConsumirServiciosFacturacionElectronica firmElectronica = new ConsumirServiciosFacturacionElectronica();
        public event EventHandler Finalizar;    

        private void OnFinalizar()
        {
            if (Finalizar != null)
                Finalizar(this, new EventArgs());
        }

        public Form1()
        {
            InitializeComponent();
            userLoading1.pboxLoading.Visible = false;
            firmElectronica.IniciaLoading += firmElectronica_IniciaLoading;
            firmElectronica.FinilizaLoading += firmElectronica_FinilizaLoading;
            ofdArchivos.FileName = string.Empty;
            ofdArchivos.Filter = "Xml Files (.xml)|*.xml|All Files (*.*)|*.*";
            this.Finalizar += Form1_Finalizar;
        }

        void Form1_Finalizar(object sender, EventArgs e)
        {
            SetVisibility(false);
        }

        void firmElectronica_FinilizaLoading(object sender, EventArgs e)
        {
            SetVisibility(false);
        }

        void firmElectronica_IniciaLoading(object sender, EventArgs e)
        {
            SetTextXml(string.Empty);
            SetVisibility(true);
        }

        private void btnBuscarArchivo_Click(object sender, EventArgs e)
        {
            ofdArchivos.ShowDialog();
        }

        private void ofdArchivos_FileOk(object sender, CancelEventArgs e)
        {
            txtDireccion.Text = ofdArchivos.FileName;
        }

        private void btnEnviarXml_Click(object sender, EventArgs e)
        {
            p1 = new Thread(EnviarXml);
            p1.IsBackground = true;
            p1.Start();
        }

        private void btnFirmar_Click(object sender, EventArgs e)
        {
            p2 = new Thread(Firmar);
            p2.IsBackground = true;
            p2.Start();
        }

        private void btnConsultar_Click(object sender, EventArgs e)
        {
            p3 = new Thread(Consultar);
            p3.IsBackground = true;
            p3.Start();
        }

        private void EnviarXml()
        {
            SetTextXml(
                firmElectronica.FormatXml(
                    firmElectronica.EnviarFacturaString(firmElectronica.FirmarXml(txtDireccion.Text),
                                                        rdnProduccion.Checked ? 'P' : 'C')));
        }

        private void Firmar()
        {
            SetTextXml(firmElectronica.ObtenerXml(firmElectronica.FirmarXml(txtDireccion.Text)));
        }

        private void Consultar()
        {
            SetTextXml(firmElectronica.FormatXml(firmElectronica.ConsultarFacturaString(txtClaveAcceso.Text, rdnProduccion.Checked ? 'P' : 'C').Replace("&gt;", ">").Replace("&lt;","<")));
        }

        private void SetVisibility(bool estado)
        {
            if (userLoading1.pboxLoading.InvokeRequired ||
                btnBuscarArchivo.InvokeRequired ||
                btnConsultar.InvokeRequired ||
                btnEnviarXml.InvokeRequired ||
                btnFirmar.InvokeRequired ||
                txtClaveAcceso.InvokeRequired ||
                txtDireccion.InvokeRequired ||
                rtbXmlViewer.InvokeRequired || 
                btnCancelar.InvokeRequired ||
                btnEnvioPorDemanda.InvokeRequired)
            {
                SetVisibilityCallback d = SetVisibility;
                Invoke(d, new object[] { estado });
            }
            else
            {
                userLoading1.pboxLoading.Visible = estado;
                btnBuscarArchivo.Enabled = !estado;
                btnConsultar.Enabled = !estado;
                btnEnviarXml.Enabled = !estado;
                btnFirmar.Enabled = !estado;
                txtClaveAcceso.Enabled = !estado;
                txtDireccion.Enabled = !estado;
                rtbXmlViewer.Enabled = !estado;
                btnEnvioPorDemanda.Enabled = !estado;
            }
        }

        private void SetTextXml(string text)
        {
            if (rtbXmlViewer.InvokeRequired || xmlEditor1.xmlTextBox.InvokeRequired)
            {
                SetTextCallback d = SetTextXml;
                Invoke(d, new object[] { text });
            }
            else
            {
                rtbXmlViewer.Text = text;
                xmlEditor1.xmlTextBox.Text = text;
            }
        }

        private void SetTextControls(string text)
        {
            if (txtDireccion.InvokeRequired || txtClaveAcceso.InvokeRequired)
            {
                SetTextCallback d = SetTextControls;
                Invoke(d, new object[] { text });
            }
            else
            {
                txtDireccion.Text = text;
                txtClaveAcceso.Text = text;
            }
        }
        public byte[] XMLtoByte(string path)
        {
            FileStream fs = System.IO.File.OpenRead(path);
            byte[] bytes = ReadWholeArray(fs);
            return bytes;
        }

        public static byte[] ReadWholeArray(Stream stream)
        {
            byte[] data = new byte[stream.Length];

            int offset = 0;
            int remaining = data.Length;
            while (remaining > 0)
            {
                int read = stream.Read(data, offset, remaining);
                if (read <= 0)
                    throw new EndOfStreamException
                        (String.Format("End of stream reached with {0} bytes left to read", remaining));
                remaining -= read;
                offset += read;
            }

            return data;
        }

        private void btnEnvioPorDemanda_Click(object sender, EventArgs e)
        {
            p4 = new Thread(EnviarXmlFirmado);
            p4.IsBackground = true;
            p4.Start();
        }

        private void EnviarXmlFirmado()
        {
            SetTextXml(
               firmElectronica.FormatXml(
                   firmElectronica.EnviarFacturaString(XMLtoByte(txtDireccion.Text), rdnProduccion.Checked ? 'P' : 'C')));
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.ExitThread();
            GC.Collect();
            this.Dispose();
        }

        private void xmlEditor1_Load(object sender, EventArgs e)
        {
            xmlEditor1.xmlTextBox.Width = xmlEditor1.Width;
            xmlEditor1.xmlTextBox.Height = xmlEditor1.Height;
        }

        private void rdnPruebas_CheckedChanged(object sender, EventArgs e)
        {
            if(rdnPruebas.Checked)
            {
                rdnProduccion.Checked = false;
            }
        }

        private void rdnProduccion_CheckedChanged(object sender, EventArgs e)
        {
            if (rdnProduccion.Checked)
            {
                rdnPruebas.Checked = false;
            }
        }

        private void btnCancelar_Click(object sender, EventArgs e)
        {
            OnFinalizar();
            Cancelar();
        }

        private void Cancelar()
        {
            Thread.Sleep(100);
            if (p1 != null)
            {
                if (p1.ThreadState == ThreadState.Running
                    || p1.ThreadState == ThreadState.Background)
                {
                    p1.Abort();
                    p1.Suspend();
                }
            }
            if (p2 != null)
            {
                if (p2.ThreadState == ThreadState.Running
                    || p2.ThreadState == ThreadState.Background)
                {
                    p2.Abort();
                    p2.Suspend();
                }
            }
            if (p3 != null)
            {
                if (p3.ThreadState == ThreadState.Running
                    || p3.ThreadState == ThreadState.Background)
                {
                    p3.Abort();
                    p3.Suspend();
                }
            }
            if (p4 != null)
            {
                if (p4.ThreadState == ThreadState.Running
                    || p4.ThreadState == ThreadState.Background)
                {
                    p4.Abort();
                    p4.Suspend();
                }
            }
        }

        private void TestXml()
        {
            
        }
    }
}
